// -*- c-basic-offset: 2 default-tab-width: 2 indent-tabs-mode: t -*-
// vim: autoindent tabstop=2 noexpandtab shiftwidth=2 softtabstop=2
#ifndef _C_VECTOR_H_
#define _C_VECTOR_H_

#include "stdint.h"
#include "util.h"

namespace R {

	template <class T>
	class CVector {
		T*       content;
		uint64_t capacity;
		uint64_t _size;

		void ensureCapacity(uint64_t newSize) {
			if(newSize >= capacity) {
				uint64_t newCapacity = capacity<<1;
				if(newCapacity <= newSize)
					newCapacity = newSize + 1;

				T* newContent = new T[newCapacity]();
				memcpy(newContent, content, _size*sizeof(T));
				delete[] content;
				capacity = newCapacity;
				content = newContent;
			}
		}

	public:
		CVector(uint64_t initialCapacity = 16) {
			content  = new T[initialCapacity]();
			capacity = initialCapacity;
			_size    = 0;
		}

		T& head() {
			return get(_size-1);
		}

		T& tail() {
			return get(0);
		}

		T& pushRoom() {
			ensureCapacity(++_size);
			return head();
		}

		void set(T& element, uint64_t idx) {
			ensureCapacity(idx + 1);
			content[idx] = element;
			_size = idx < _size ? _size : idx + 1;
		}

		T& get(uint64_t idx) {
		  rerror_on(idx >= _size, "out of bound: "WORD"/"WORD"", idx, _size);
		  return content[idx];
		}
		
		uint64_t size() {
		  return _size;
		}

		void push(T& element) {
		  set(element, _size);
		}

		T& pop(int nb_elem = 1) {
		  rerror_on((_size -= nb_elem) < 0 || (nb_elem < 0), "no such element or bad argument");
		  return content[_size];
		}

		int has(T& element) {
			for(uint64_t i = 0; i < _size; i++){
				if(content[i] == element){
					return i;
				}
			}
			return -1;
		}

		~CVector() { 
			delete[] content; 
		}
	};
}

#endif
